package repository

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/product/model"

	"github.com/volatiletech/null/v8"
	"github.com/volatiletech/sqlboiler/v4/boil"
	"github.com/volatiletech/sqlboiler/v4/queries/qm"
	"github.com/zeromicro/go-zero/core/stores/cache"
)

type (
	// CurrentProductRepository is an interface to be customized, add more methods here,
	// and implement the added methods in customCurrentProductRepository.
	CurrentProductRepository interface {
		FindOne(ctx context.Context, id uint64) (*model.ProductProduct, error)
		FindOneWithExpire(
			ctx context.Context,
			id uint64,
			expire time.Duration,
		) (*model.ProductProduct, error)
		FindOneNoCache(
			ctx context.Context,
			conn boil.ContextExecutor,
			id uint64,
		) (*model.ProductProduct, error)
		GetList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductProduct, int64, error) // ##24.12.16##
		Insert(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.ProductProduct,
			rel *model.ProductRel,
		) error // #24.12.17#
		Update(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.ProductProduct,
			rel *model.ProductRel,
		) error
		UpdateBatch(ctx context.Context, tx boil.ContextExecutor, ids []uint64, cols model.M) error
		SoftDelete(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		Restore(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		ForceDelete(ctx context.Context, tx boil.ContextExecutor, id uint64) error
		ForceDeleteBatch(ctx context.Context, tx boil.ContextExecutor, ids []uint64) error

		GetDetailList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductDetail, int64, error) // #24.12.17#
		GetRelationshipList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductTermRelationship, int64, error) // ##24.11.08##
		GetEntryList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductKnowledgeBaseRelationship, int64, error) // #24.12.17#
		GetMeta(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductMetum, int64, error) // ##24.12.17##
		UpdateMetum(
			ctx context.Context,
			tx boil.ContextExecutor,
			metum *model.ProductMetum,
		) error // #25.01.17#
		GetMedia(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductAttachmentRelationship, int64, error) // ##24.12.17##
		GetAttributeList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductAttribute, int64, error) // ##25.01.07##
		GetAttributeOptionList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductAttributeOption, int64, error) // ##25.01.07##
		GetVariationList(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductVariation, int64, error) // #24.12.17#
		GetVariationMeta(
			ctx context.Context,
			cols model.M,
			withCount int,
			filter map[string]map[string][]any,
		) ([]*model.ProductVariationMetum, int64, error) // #24.12.17#
		InsertSearchLog(
			ctx context.Context,
			tx boil.ContextExecutor,
			data *model.ProductUserSearchLog,
		) error
		UpdateProductVariationMeta(
			ctx context.Context,
			tx boil.ContextExecutor,
			meta []*model.ProductVariationMetum,
			delMetaIds []uint64,
		) error // #25.01.16#
		UpdateProductVariationMetum(
			ctx context.Context,
			tx boil.ContextExecutor,
			metum *model.ProductVariationMetum,
		) error // #25.01.16#
	}

	customCurrentProductRepository struct {
		modelx.CachedConn
		mysqlConn           *sql.DB
		cacheIdPrefix       string
		cacheIdExpirePrefix string
	}

	// Custom struct for selecting a subset of data
	RandomInfo struct {
		MaxId int     `boil:"max_id"`
		MinId int     `boil:"min_id"`
		Rand  float64 `boil:"rand"`
	}
)

// NewCurrentProductRepository returns a repository for the database table.
func NewCurrentProductRepository(mysqlConn *sql.DB, cacheConf cache.CacheConf) CurrentProductRepository {
	return &customCurrentProductRepository{
		CachedConn:          modelx.NewConn(mysqlConn, cacheConf),
		mysqlConn:           mysqlConn,
		cacheIdPrefix:       "cache:product:products:id:",
		cacheIdExpirePrefix: "cache:product:products:id:expire:",
	}
}

func (r *customCurrentProductRepository) FindOne(
	ctx context.Context,
	id uint64,
) (*model.ProductProduct, error) {
	cacheIdKey := r.formatPrimary(id)
	var resp model.ProductProduct
	err := r.QueryCtx(ctx, &resp, cacheIdKey, func(ctx context.Context, conn *sql.DB, v any) error {
		data, err := model.FindProductProduct(ctx, conn, id)
		if err != nil {
			return err
		}

		*v.(*model.ProductProduct) = *data

		return nil
	})

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customCurrentProductRepository) FindOneWithExpire(
	ctx context.Context,
	id uint64,
	expire time.Duration,
) (*model.ProductProduct, error) {
	cacheIdKey := r.formatPrimary(id)
	var resp model.ProductProduct
	err := r.QueryWithExpireCtx(ctx, &resp, cacheIdKey, expire, func(ctx context.Context, conn *sql.DB, v any) error {
		data, err := model.FindProductProduct(ctx, conn, id)
		if err != nil {
			return err
		}

		*v.(*model.ProductProduct) = *data

		return nil
	})

	switch err {
	case nil:
		return &resp, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customCurrentProductRepository) FindOneNoCache(
	ctx context.Context,
	conn boil.ContextExecutor,
	id uint64,
) (*model.ProductProduct, error) {
	var db boil.ContextExecutor = r.mysqlConn
	if conn != nil {
		db = conn
	}
	data, err := model.FindProductProduct(ctx, db, id)
	switch err {
	case nil:
		return data, nil
	case sql.ErrNoRows:
		return nil, model.ErrNotFound
	default:
		return nil, err
	}
}

func (r *customCurrentProductRepository) GetList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductProduct, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	var statistic bool
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductProductColumns.ID+" DESC"))
					mods = append(mods, model.ProductProductWhere.ID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductProductColumns.ID+" ASC"))
					mods = append(mods, model.ProductProductWhere.ID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		case "search":
			if val, ok := v.(string); ok && len(val) > 0 { // 搜索
				likeVal := fmt.Sprintf("%%%s%%", val)
				mods = append(mods, qm.Where(fmt.Sprintf(
					"(%s LIKE ? OR %s LIKE ?)",
					model.ProductProductColumns.Title,
					model.ProductProductColumns.Slug), likeVal, likeVal))
			}
		case "statistic":
			if val, ok := v.(string); ok && val == "1" { // 按 Status 统计
				statistic = true
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductProductColumns.ID:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.ID, opMap)...)
		case model.ProductProductColumns.CategoryID:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.CategoryID, opMap)...)
		case model.ProductProductColumns.ParentID:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.ParentID, opMap)...)
		case model.ProductProductColumns.ProductAuthorID:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.ProductAuthorID, opMap)...)
		case model.ProductProductColumns.ProductCode:
			mods = append(mods, modelx.GetStringMods(model.ProductProductColumns.ProductCode, opMap)...)
		case model.ProductProductColumns.Title:
			mods = append(mods, modelx.GetStringMods(model.ProductProductColumns.Title, opMap)...)
		case model.ProductProductColumns.Slug:
			mods = append(mods, modelx.GetStringMods(model.ProductProductColumns.Slug, opMap)...)
		case model.ProductProductColumns.Excerpt:
			mods = append(mods, modelx.GetStringMods(model.ProductProductColumns.Excerpt, opMap)...)
		case model.ProductProductColumns.GUID:
			mods = append(mods, modelx.GetStringMods(model.ProductProductColumns.GUID, opMap)...)
		case model.ProductProductColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.Status, opMap)...)
		case model.ProductProductColumns.ProductDate:
			mods = append(mods, modelx.GetTimeMods(model.ProductProductColumns.ProductDate, opMap)...)
		case model.ProductProductColumns.ProductModifiedDate:
			mods = append(mods, modelx.GetTimeMods(model.ProductProductColumns.ProductModifiedDate, opMap)...)
		case model.ProductProductColumns.DeletedAt:
			mods = append(mods, modelx.GetTimeMods(model.ProductProductColumns.DeletedAt, opMap)...)
		case model.ProductProductColumns.VirtualType:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.VirtualType, opMap)...)
		case model.ProductProductColumns.SortOrder:
			mods = append(mods, modelx.GetIntMods(model.ProductProductColumns.SortOrder, opMap)...)
		}
	}

	if statistic {
		mods = append(mods, qm.Select(fmt.Sprintf(
			"%s, count(%s) as %s",
			model.ProductProductColumns.Status,
			model.ProductProductColumns.Status,
			model.ProductProductColumns.SortOrder,
		)))
		mods = append(mods, qm.GroupBy(model.ProductProductColumns.Status))
		preList, preErr := model.ProductProducts(mods...).All(ctx, r.mysqlConn)
		if preErr != nil {
			err = preErr
			return
		}

		return preList, 0, nil
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductProducts(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductProductColumns.ID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductProducts(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) Insert(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.ProductProduct,
	rel *model.ProductRel,
) error {
	err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		err := data.Insert(ctx, db, boil.Infer())
		if err != nil {
			return err
		}

		if rel == nil {
			return nil
		}

		pid := data.ID
		if rel.Detail != nil {
			rel.Detail.ProductID = pid
			err = rel.Detail.Insert(ctx, db, boil.Infer())
			if err != nil {
				return err
			}
		}

		if len(rel.Meta) > 0 {
			for _, v := range rel.Meta {
				v.ProductID = pid
				err = v.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Media) > 0 {
			for _, v := range rel.Media {
				v.ObjectID = pid
				v.ObjectType = uint16(globalkey.AttachmentLogTypeProduct)
				err = v.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.CategoryIds) > 0 {
			for _, cid := range rel.CategoryIds {
				var relationShip model.ProductTermRelationship
				relationShip.ObjectID = pid
				relationShip.ObjectType = uint16(globalkey.PostTypeProduct)
				relationShip.TermID = uint64(cid)
				err = relationShip.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.TagIds) > 0 {
			for _, tid := range rel.TagIds {
				var relationShip model.ProductTermRelationship
				relationShip.ObjectID = pid
				relationShip.ObjectType = uint16(globalkey.PostTypeProduct)
				relationShip.TermID = uint64(tid)
				err = relationShip.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.RelationShips) > 0 {
			for _, v := range rel.RelationShips {
				v.ProductID = pid
				err = v.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		optionKeyMap := make(map[string]uint64) // 规格相关，属性值Key=>属性值ID
		if len(rel.Attributes) > 0 {
			for _, item := range rel.Attributes {
				if len(item.Options) > 0 {
					attr := item.Attribute
					attr.ProductID = pid
					err = attr.Insert(ctx, db, boil.Infer())
					if err != nil {
						return err
					}

					attrId := attr.ProductAttributeID
					for _, opt := range item.Options {
						optType := opt.Status
						if optType < 0 { // 是规格相关属性值 -1、-2、-3 对应 item.Options 的序号
							if key, ok := rel.OptionKeyMap[optType]; ok {
								opt.Status = int8(globalkey.StatusEnabled)
								opt.AttributeID = attrId
								err = opt.Insert(ctx, db, boil.Infer())
								if err != nil {
									return err
								}

								optionKeyMap[key] = opt.OptionID
							}
						} else { // globalkey.StatusApproved = 1
							opt.AttributeID = attrId
							err = opt.Insert(ctx, db, boil.Infer())
							if err != nil {
								return err
							}
						}
					}
				}
			}
		}

		if len(rel.Variations) > 0 {
			for _, item := range rel.Variations {
				variation := item.Variation
				variation.ProductID = pid
				err = variation.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}

				variationId := variation.ProductVariationID
				if len(item.Meta) > 0 {
					for _, metum := range item.Meta {
						if metum.MetaKey == "_sku_key" && metum.MetaValue.Valid {
							val := metum.MetaValue.String
							keys := strings.Split(val, "_-_")
							var newVals []string
							if len(keys) > 0 {
								for _, key := range keys {
									if optId, ok := optionKeyMap[key]; ok {
										newVals = append(newVals, strconv.FormatInt(int64(optId), 10))
									}
								}
							}
							metum.MetaValue = null.StringFrom(strings.Join(newVals, ","))
						}
						metum.ProductID = variationId
						err = metum.Insert(ctx, db, boil.Infer())
						if err != nil {
							return err
						}
					}
				}
			}
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customCurrentProductRepository) Update(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.ProductProduct,
	rel *model.ProductRel,
) error {
	err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.ProductProductColumns.ID,
			model.ProductProductColumns.DeletedAt,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		if rel == nil {
			return nil
		}

		pid := data.ID
		if rel.Detail != nil && rel.Detail.ProductID == pid {
			if rel.Detail.DetailID > 0 {
				_, err = rel.Detail.Update(ctx, db, boil.Blacklist(
					model.ProductDetailColumns.DetailID,
					model.ProductDetailColumns.ProductID,
				))
				if err != nil {
					return err
				}
			} else {
				err = rel.Detail.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Meta) > 0 {
			for _, v := range rel.Meta {
				if v.MetaID > 0 {
					_, err = v.Update(ctx, db, boil.Blacklist(
						model.ProductMetumColumns.MetaID,
						model.ProductMetumColumns.ProductID,
						model.ProductMetumColumns.MetaKey,
					))
				} else {
					v.ProductID = pid
					err = v.Insert(ctx, db, boil.Infer())
				}
				if err != nil {
					return err
				}
			}
		}

		if len(rel.Media) > 0 {
			for _, v := range rel.Media {
				if v.AttachmentRelationshipID > 0 {
					_, err = v.Update(ctx, db, boil.Blacklist(
						model.ProductAttachmentRelationshipColumns.AttachmentRelationshipID,
						model.ProductAttachmentRelationshipColumns.ObjectID,
						model.ProductAttachmentRelationshipColumns.ObjectType,
						model.ProductAttachmentRelationshipColumns.AttachmentID,
					))
				} else {
					v.ObjectID = pid
					v.ObjectType = uint16(globalkey.AttachmentLogTypeProduct)
					err = v.Insert(ctx, db, boil.Infer())
				}
				if err != nil {
					return err
				}
			}
		}

		objectType := uint16(globalkey.PostTypeProduct)
		if len(rel.CategoryIds) > 0 {
			for _, cid := range rel.CategoryIds {
				var relationShip model.ProductTermRelationship
				relationShip.ObjectID = pid
				relationShip.ObjectType = objectType
				relationShip.TermID = uint64(cid)
				err = relationShip.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}
		if len(rel.TagIds) > 0 {
			for _, tid := range rel.TagIds {
				var relationShip model.ProductTermRelationship
				relationShip.ObjectID = pid
				relationShip.ObjectType = objectType
				relationShip.TermID = uint64(tid)
				err = relationShip.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}
		if len(rel.Terms) > 0 {
			for _, v := range rel.Terms {
				if v.TermRelationshipID > 0 {
					_, err = v.Update(ctx, db, boil.Blacklist(
						model.ProductTermRelationshipColumns.TermRelationshipID,
						model.ProductTermRelationshipColumns.ObjectID,
						model.ProductTermRelationshipColumns.ObjectType,
						model.ProductTermRelationshipColumns.TermID,
					))
					if err != nil {
						return err
					}
				}
			}
		}

		if len(rel.RelationShips) > 0 {
			for _, v := range rel.RelationShips {
				if v.ProductRelationshipID > 0 {
					_, err = v.Update(ctx, db, boil.Blacklist(
						model.ProductKnowledgeBaseRelationshipColumns.ProductRelationshipID,
						model.ProductKnowledgeBaseRelationshipColumns.ProductID,
					))
				} else {
					v.ProductID = pid
					err = v.Insert(ctx, db, boil.Infer())
				}
				if err != nil {
					return err
				}
			}
		}

		optionKeyMap := make(map[string]uint64) // 规格相关，属性值Key=>属性值ID
		if len(rel.Attributes) > 0 {
			for _, item := range rel.Attributes {
				if len(item.Options) > 0 {
					attr := item.Attribute
					if attr.ProductAttributeID > 0 {
						_, err = attr.Update(ctx, db, boil.Blacklist(
							model.ProductAttributeColumns.ProductAttributeID,
							model.ProductAttributeColumns.ProductID,
						))
					} else {
						attr.ProductID = pid
						err = attr.Insert(ctx, db, boil.Infer())
					}
					if err != nil {
						return err
					}

					attrId := attr.ProductAttributeID
					for _, opt := range item.Options {
						optType := opt.Status
						if optType < 0 { // 是规格相关属性值
							if key, ok := rel.OptionKeyMap[optType]; ok {
								if opt.OptionID > 0 {
									_, err = opt.Update(ctx, db, boil.Blacklist(
										model.ProductAttributeOptionColumns.OptionID,
										model.ProductAttributeOptionColumns.AttributeID,
									))
								} else {
									opt.Status = int8(globalkey.StatusEnabled)
									opt.AttributeID = attrId
									err = opt.Insert(ctx, db, boil.Infer())
								}
								if err != nil {
									return err
								}

								optionKeyMap[key] = opt.OptionID
							}
						} else {
							if opt.OptionID > 0 {
								_, err = opt.Update(ctx, db, boil.Blacklist(
									model.ProductAttributeOptionColumns.OptionID,
									model.ProductAttributeOptionColumns.AttributeID,
								))
							} else {
								opt.AttributeID = attrId
								err = opt.Insert(ctx, db, boil.Infer())
							}
							if err != nil {
								return err
							}
						}
					}
				}
			}
		}

		if len(rel.Variations) > 0 {
			for _, item := range rel.Variations {
				variation := item.Variation
				if variation.ProductVariationID > 0 {
					_, err = variation.Update(ctx, db, boil.Blacklist(
						model.ProductVariationColumns.ProductVariationID,
						model.ProductVariationColumns.ProductID,
					))
				} else {
					variation.ProductID = pid
					err = variation.Insert(ctx, db, boil.Infer())
				}
				if err != nil {
					return err
				}

				variationId := variation.ProductVariationID
				if len(item.Meta) > 0 {
					for _, metum := range item.Meta {
						if metum.MetaKey == "_sku_key" {
							val := metum.MetaValue.String
							keys := strings.Split(val, "_-_")
							var newVals []string
							if len(keys) > 0 {
								for _, key := range keys {
									if optId, ok := optionKeyMap[key]; ok {
										newVals = append(newVals, strconv.FormatInt(int64(optId), 10))
									}
								}
							}
							metum.MetaValue = null.StringFrom(strings.Join(newVals, ","))
						}
						if metum.MetaID > 0 {
							_, err = metum.Update(ctx, db, boil.Blacklist(
								model.ProductVariationMetumColumns.MetaID,
								model.ProductVariationMetumColumns.ProductID,
								model.ProductVariationMetumColumns.MetaKey,
							))
						} else {
							metum.ProductID = variationId
							err = metum.Insert(ctx, db, boil.Infer())
						}
						if err != nil {
							return err
						}
					}
				}
			}
		}

		if len(rel.DelRelationIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductKnowledgeBaseRelationshipWhere.ProductRelationshipID.IN(rel.DelRelationIds))
			_, err = model.ProductKnowledgeBaseRelationships(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelMetaIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductMetumWhere.MetaID.IN(rel.DelMetaIds))
			_, err = model.ProductMeta(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelVariationMetaIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductVariationMetumWhere.MetaID.IN(rel.DelVariationMetaIds))
			_, err = model.ProductVariationMeta(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelMediaIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductAttachmentRelationshipWhere.AttachmentRelationshipID.IN(rel.DelMediaIds))
			_, err = model.ProductAttachmentRelationships(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelTermIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductTermRelationshipWhere.TermRelationshipID.IN(rel.DelTermIds))
			_, err = model.ProductTermRelationships(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelAttrOptIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductAttributeOptionWhere.OptionID.IN(rel.DelAttrOptIds))
			_, err = model.ProductAttributeOptions(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelAttributeIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductAttributeWhere.ProductAttributeID.IN(rel.DelAttributeIds))
			_, err = model.ProductAttributes(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}
		if len(rel.DelVariationIds) > 0 {
			var mods []qm.QueryMod
			mods = append(mods, model.ProductVariationWhere.ProductVariationID.IN(rel.DelVariationIds))
			_, err = model.ProductVariations(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customCurrentProductRepository) UpdateBatch(
	ctx context.Context,
	tx boil.ContextExecutor,
	ids []uint64,
	cols model.M,
) error {
	if len(ids) > 0 {
		err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
			var db boil.ContextExecutor
			if tx != nil {
				db = tx
			} else {
				db = conn
			}

			var mods []qm.QueryMod
			mods = append(mods, model.ProductProductWhere.ID.IN(ids))

			rowsAff, err := model.ProductProducts(mods...).UpdateAll(ctx, db, cols)
			if err != nil {
				return err
			}

			if rowsAff == 0 {
				return model.ErrNotUpdated
			}

			return nil
		}, r.formatPrimaries(ids)...)

		return err
	}

	return nil
}

func (r *customCurrentProductRepository) SoftDelete(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	if data.Status == uint16(globalkey.PostStatusTrash) {
		return nil
	}

	data.DelStatus = data.Status
	data.Status = uint16(globalkey.PostStatusTrash)
	data.DeletedAt = null.TimeFrom(time.Now())

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.ProductProductColumns.ID,
			model.ProductProductColumns.ProductModifiedDate,
			model.ProductProductColumns.ProductModifiedGMT,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customCurrentProductRepository) Restore(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	if data.Status != uint16(globalkey.PostStatusTrash) {
		return nil
	}

	data.Status = data.DelStatus
	data.DeletedAt = null.TimeFromPtr(nil)

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Update(ctx, db, boil.Blacklist(
			model.ProductProductColumns.ID,
			model.ProductProductColumns.ProductModifiedDate,
			model.ProductProductColumns.ProductModifiedGMT,
		))
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotUpdated
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customCurrentProductRepository) ForceDelete(
	ctx context.Context,
	tx boil.ContextExecutor,
	id uint64,
) error {
	data, err := r.FindOneNoCache(ctx, tx, id)
	if err != nil {
		if err == model.ErrNotFound {
			return nil
		}

		return err
	}

	err = r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = conn
		}

		rowsAff, err := data.Delete(ctx, db)
		if err != nil {
			return err
		}

		if rowsAff == 0 {
			return model.ErrNotDeleted
		}

		return nil
	}, r.getCacheKeys(data)...)

	return err
}

func (r *customCurrentProductRepository) ForceDeleteBatch(
	ctx context.Context,
	tx boil.ContextExecutor,
	ids []uint64,
) error {
	if len(ids) > 0 {
		err := r.ExecCtx(ctx, func(ctx context.Context, conn *sql.DB) error {
			var db boil.ContextExecutor
			if tx != nil {
				db = tx
			} else {
				db = conn
			}

			var mods []qm.QueryMod
			mods = append(mods, model.ProductProductWhere.ID.IN(ids))

			rowsAff, err := model.ProductProducts(mods...).DeleteAll(ctx, db)
			if err != nil {
				return err
			}

			if rowsAff == 0 {
				return model.ErrNotDeleted
			}

			return nil
		}, r.formatPrimaries(ids)...)

		return err
	}

	return nil
}

func (r *customCurrentProductRepository) getCacheKeys(data *model.ProductProduct) []string {
	if data == nil {
		return []string{}
	}

	cacheIdKey := r.formatPrimary(data.ID)
	cacheIdExpireKey := r.formatPrimaryWithExpire(data.ID)
	cacheKeys := []string{
		cacheIdKey,
		cacheIdExpireKey,
	}

	return cacheKeys
}

func (r *customCurrentProductRepository) formatPrimary(primary any) string {
	return fmt.Sprintf("%s%v", r.cacheIdPrefix, primary)
}

func (r *customCurrentProductRepository) formatPrimaryWithExpire(primary any) string {
	return fmt.Sprintf("%s%v", r.cacheIdExpirePrefix, primary)
}

func (r *customCurrentProductRepository) formatPrimaries(primaries []uint64) []string {
	var resp []string
	for _, primary := range primaries {
		resp = append(resp, r.formatPrimary(primary))
		resp = append(resp, r.formatPrimaryWithExpire(primary))
	}

	return resp
}

func (r *customCurrentProductRepository) queryPrimary(ctx context.Context, conn *sql.DB, v, primary any) error {
	var pid uint64
	if jsonId, ok := primary.(json.Number); ok {
		if int64Id, err := jsonId.Int64(); err == nil {
			pid = uint64(int64Id)
		} else {
			return err
		}
	}

	data, err := model.FindProductProduct(ctx, conn, pid)
	if err != nil {
		return err
	}

	*v.(*model.ProductProduct) = *data

	return nil
}

func (r *customCurrentProductRepository) GetDetailList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductDetail, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductDetailColumns.DetailID+" DESC"))
					mods = append(mods, model.ProductDetailWhere.DetailID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductDetailColumns.DetailID+" ASC"))
					mods = append(mods, model.ProductDetailWhere.DetailID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductDetailColumns.DetailID:
			mods = append(mods, modelx.GetIntMods(model.ProductDetailColumns.DetailID, opMap)...)
		case model.ProductDetailColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.ProductDetailColumns.ProductID, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductDetails(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductDetailColumns.DetailID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductDetails(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetRelationshipList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductTermRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductTermRelationshipColumns.TermRelationshipID+" DESC"))
					mods = append(mods, model.ProductTermRelationshipWhere.TermRelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductTermRelationshipColumns.TermRelationshipID+" ASC"))
					mods = append(mods, model.ProductTermRelationshipWhere.TermRelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductTermRelationshipColumns.TermRelationshipID:
			mods = append(mods, modelx.GetIntMods(model.ProductTermRelationshipColumns.TermRelationshipID, opMap)...)
		case model.ProductTermRelationshipColumns.ObjectID:
			mods = append(mods, modelx.GetIntMods(model.ProductTermRelationshipColumns.ObjectID, opMap)...)
		case model.ProductTermRelationshipColumns.ObjectType:
			mods = append(mods, modelx.GetIntMods(model.ProductTermRelationshipColumns.ObjectType, opMap)...)
		case model.ProductTermRelationshipColumns.TermID:
			mods = append(mods, modelx.GetIntMods(model.ProductTermRelationshipColumns.TermID, opMap)...)
		case model.ProductTermRelationshipColumns.TermOrder:
			mods = append(mods, modelx.GetIntMods(model.ProductTermRelationshipColumns.TermOrder, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductTermRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductTermRelationshipColumns.TermRelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductTermRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetEntryList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductKnowledgeBaseRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductKnowledgeBaseRelationshipColumns.ProductRelationshipID+" DESC"))
					mods = append(mods, model.ProductKnowledgeBaseRelationshipWhere.ProductRelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductKnowledgeBaseRelationshipColumns.ProductRelationshipID+" ASC"))
					mods = append(mods, model.ProductKnowledgeBaseRelationshipWhere.ProductRelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductKnowledgeBaseRelationshipColumns.ProductRelationshipID:
			mods = append(mods, modelx.GetIntMods(model.ProductKnowledgeBaseRelationshipColumns.ProductRelationshipID, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.ProductKnowledgeBaseRelationshipColumns.ProductID, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ToEntryID:
			mods = append(mods, modelx.GetIntMods(model.ProductKnowledgeBaseRelationshipColumns.ToEntryID, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ToEntryName:
			mods = append(mods, modelx.GetStringMods(model.ProductKnowledgeBaseRelationshipColumns.ToEntryName, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ToEntrySlug:
			mods = append(mods, modelx.GetStringMods(model.ProductKnowledgeBaseRelationshipColumns.ToEntrySlug, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ToEntryGroupID:
			mods = append(mods, modelx.GetIntMods(model.ProductKnowledgeBaseRelationshipColumns.ToEntryGroupID, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ToEntryGroupName:
			mods = append(mods, modelx.GetStringMods(model.ProductKnowledgeBaseRelationshipColumns.ToEntryGroupName, opMap)...)
		case model.ProductKnowledgeBaseRelationshipColumns.ToEntryGroupSlug:
			mods = append(mods, modelx.GetStringMods(model.ProductKnowledgeBaseRelationshipColumns.ToEntryGroupSlug, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductKnowledgeBaseRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductKnowledgeBaseRelationshipColumns.ProductRelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductKnowledgeBaseRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetMeta(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductMetum, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductMetumColumns.MetaID+" DESC"))
					mods = append(mods, model.ProductMetumWhere.MetaID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductMetumColumns.MetaID+" ASC"))
					mods = append(mods, model.ProductMetumWhere.MetaID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductMetumColumns.MetaID:
			mods = append(mods, modelx.GetIntMods(model.ProductMetumColumns.MetaID, opMap)...)
		case model.ProductMetumColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.ProductMetumColumns.ProductID, opMap)...)
		case model.ProductMetumColumns.MetaKey:
			mods = append(mods, modelx.GetStringMods(model.ProductMetumColumns.MetaKey, opMap)...)
		case model.ProductMetumColumns.MetaValue:
			mods = append(mods, modelx.GetStringMods(model.ProductMetumColumns.MetaValue, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductMeta(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductMetumColumns.MetaID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductMeta(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) UpdateMetum(
	ctx context.Context,
	tx boil.ContextExecutor,
	metum *model.ProductMetum,
) error {
	if metum.ProductID > 0 && len(metum.MetaKey) > 0 {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = r.mysqlConn
		}

		var mods []qm.QueryMod
		mods = append(mods, model.ProductMetumWhere.ProductID.EQ(metum.ProductID))
		mods = append(mods, model.ProductMetumWhere.MetaKey.EQ(metum.MetaKey))
		list, err := model.ProductMeta(mods...).All(ctx, db)
		if err != nil {
			if err == sql.ErrNoRows {
				return metum.Insert(ctx, db, boil.Infer())
			}

			return err
		}

		if len(list) == 0 {
			return metum.Insert(ctx, db, boil.Infer())
		}

		_, err = model.ProductMeta(mods...).UpdateAll(ctx, db, model.M{
			model.ProductMetumColumns.MetaValue: metum.MetaValue,
		})
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *customCurrentProductRepository) GetMedia(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductAttachmentRelationship, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductAttachmentRelationshipColumns.AttachmentRelationshipID+" DESC"))
					mods = append(mods, model.ProductAttachmentRelationshipWhere.AttachmentRelationshipID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductAttachmentRelationshipColumns.AttachmentRelationshipID+" ASC"))
					mods = append(mods, model.ProductAttachmentRelationshipWhere.AttachmentRelationshipID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductAttachmentRelationshipColumns.AttachmentRelationshipID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttachmentRelationshipColumns.AttachmentRelationshipID, opMap)...)
		case model.ProductAttachmentRelationshipColumns.ObjectID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttachmentRelationshipColumns.ObjectID, opMap)...)
		case model.ProductAttachmentRelationshipColumns.ObjectType:
			mods = append(mods, modelx.GetIntMods(model.ProductAttachmentRelationshipColumns.ObjectType, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttachmentRelationshipColumns.AttachmentID, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentThumbnail:
			mods = append(mods, modelx.GetIntMods(model.ProductAttachmentRelationshipColumns.AttachmentThumbnail, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentOrder:
			mods = append(mods, modelx.GetIntMods(model.ProductAttachmentRelationshipColumns.AttachmentOrder, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentSource:
			mods = append(mods, modelx.GetStringMods(model.ProductAttachmentRelationshipColumns.AttachmentSource, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentImageURL:
			mods = append(mods, modelx.GetStringMods(model.ProductAttachmentRelationshipColumns.AttachmentImageURL, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentImageAlt:
			mods = append(mods, modelx.GetStringMods(model.ProductAttachmentRelationshipColumns.AttachmentImageAlt, opMap)...)
		case model.ProductAttachmentRelationshipColumns.AttachmentImageMeta:
			mods = append(mods, modelx.GetStringMods(model.ProductAttachmentRelationshipColumns.AttachmentImageMeta, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductAttachmentRelationships(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductAttachmentRelationshipColumns.AttachmentRelationshipID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductAttachmentRelationships(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetAttributeList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductAttribute, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductAttributeColumns.ProductAttributeID+" DESC"))
					mods = append(mods, model.ProductAttributeWhere.ProductAttributeID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductAttributeColumns.ProductAttributeID+" ASC"))
					mods = append(mods, model.ProductAttributeWhere.ProductAttributeID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductAttributeColumns.ProductAttributeID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeColumns.ProductAttributeID, opMap)...)
		case model.ProductAttributeColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeColumns.ProductID, opMap)...)
		case model.ProductAttributeColumns.TermID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeColumns.TermID, opMap)...)
		case model.ProductAttributeColumns.Taxonomy:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeColumns.Taxonomy, opMap)...)
		case model.ProductAttributeColumns.IsVariationAttribute:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeColumns.IsVariationAttribute, opMap)...)
		case model.ProductAttributeColumns.Name:
			mods = append(mods, modelx.GetStringMods(model.ProductAttributeColumns.Name, opMap)...)
		case model.ProductAttributeColumns.Slug:
			mods = append(mods, modelx.GetStringMods(model.ProductAttributeColumns.Slug, opMap)...)
		case model.ProductAttributeColumns.HasImage:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeColumns.HasImage, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductAttributes(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductAttributeColumns.ProductAttributeID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductAttributes(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetAttributeOptionList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductAttributeOption, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductAttributeOptionColumns.OptionID+" DESC"))
					mods = append(mods, model.ProductAttributeOptionWhere.OptionID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductAttributeOptionColumns.OptionID+" ASC"))
					mods = append(mods, model.ProductAttributeOptionWhere.OptionID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductAttributeOptionColumns.OptionID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeOptionColumns.OptionID, opMap)...)
		case model.ProductAttributeOptionColumns.AttributeID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeOptionColumns.AttributeID, opMap)...)
		case model.ProductAttributeOptionColumns.TaxonomyOptionID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeOptionColumns.TaxonomyOptionID, opMap)...)
		case model.ProductAttributeOptionColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeOptionColumns.Status, opMap)...)
		case model.ProductAttributeOptionColumns.Name:
			mods = append(mods, modelx.GetStringMods(model.ProductAttributeOptionColumns.Name, opMap)...)
		case model.ProductAttributeOptionColumns.Slug:
			mods = append(mods, modelx.GetStringMods(model.ProductAttributeOptionColumns.Slug, opMap)...)
		case model.ProductAttributeOptionColumns.ThumbnailID:
			mods = append(mods, modelx.GetIntMods(model.ProductAttributeOptionColumns.ThumbnailID, opMap)...)
		case model.ProductAttributeOptionColumns.ThumbnailURL:
			mods = append(mods, modelx.GetStringMods(model.ProductAttributeOptionColumns.ThumbnailURL, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductAttributeOptions(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductAttributeOptionColumns.OptionID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductAttributeOptions(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetVariationList(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductVariation, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductVariationColumns.ProductVariationID+" DESC"))
					mods = append(mods, model.ProductVariationWhere.ProductVariationID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductVariationColumns.ProductVariationID+" ASC"))
					mods = append(mods, model.ProductVariationWhere.ProductVariationID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductVariationColumns.ProductVariationID:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.ProductVariationID, opMap)...)
		case model.ProductVariationColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.ProductID, opMap)...)
		case model.ProductVariationColumns.GemPrice:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.GemPrice, opMap)...)
		case model.ProductVariationColumns.RetailPrice:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.RetailPrice, opMap)...)
		case model.ProductVariationColumns.CounterPrice:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.CounterPrice, opMap)...)
		case model.ProductVariationColumns.Weight:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.Weight, opMap)...)
		case model.ProductVariationColumns.SkuCode:
			mods = append(mods, modelx.GetStringMods(model.ProductVariationColumns.SkuCode, opMap)...)
		case model.ProductVariationColumns.SkuType:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.SkuType, opMap)...)
		case model.ProductVariationColumns.Status:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationColumns.Status, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductVariations(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductVariationColumns.ProductVariationID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductVariations(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) GetVariationMeta(
	ctx context.Context,
	cols model.M,
	withCount int,
	filter map[string]map[string][]any,
) (list []*model.ProductVariationMetum, count int64, err error) {
	var page int
	var pageSize int
	var limit int
	var selectCol string
	var mods []qm.QueryMod
	var nextCount int64
	var previousCount int64
	for k, v := range cols {
		switch k {
		case "page":
			if val, ok := v.(uint64); ok && val > 1 {
				page = int(val)
			}
		case "pageSize":
			if val, ok := v.(uint64); ok && val > 0 {
				pageSize = int(val)
			}
		case "limit":
			if val, ok := v.(uint32); ok && val > 0 {
				limit = int(val)
			}
		case "offset":
			if withCount == 2 {
				if val, ok := v.(uint32); ok && val > 0 {
					mods = append(mods, qm.Offset(int(val)))
					previousCount = 1
				}
			}
		case "orderBy":
			if val, ok := v.(string); ok && len(val) > 0 {
				mods = append(mods, qm.OrderBy(val))
			}
		case "preMinId":
			if withCount == 3 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductVariationMetumColumns.MetaID+" DESC"))
					mods = append(mods, model.ProductVariationMetumWhere.MetaID.LT(val))
					previousCount = 1
				}
			}
		case "preMaxId":
			if withCount == 4 {
				if val, ok := v.(uint64); ok && val > 0 {
					mods = append(mods, qm.OrderBy(model.ProductVariationMetumColumns.MetaID+" ASC"))
					mods = append(mods, model.ProductVariationMetumWhere.MetaID.GT(val))
					previousCount = 1
				}
			}
		case "select":
			if withCount != 5 {
				if val, ok := v.(string); ok && len(val) > 0 {
					selectCol = val
				}
			}
		}
	}

	for key, opMap := range filter {
		switch key {
		case model.ProductVariationMetumColumns.MetaID:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationMetumColumns.MetaID, opMap)...)
		case model.ProductVariationMetumColumns.ProductID:
			mods = append(mods, modelx.GetIntMods(model.ProductVariationMetumColumns.ProductID, opMap)...)
		case model.ProductVariationMetumColumns.MetaKey:
			mods = append(mods, modelx.GetStringMods(model.ProductVariationMetumColumns.MetaKey, opMap)...)
		case model.ProductVariationMetumColumns.MetaValue:
			mods = append(mods, modelx.GetStringMods(model.ProductVariationMetumColumns.MetaValue, opMap)...)
		}
	}

	if withCount >= 2 {
		if limit > 0 {
			mods = append(mods, qm.Limit(limit+1))
		}
	} else if withCount >= 0 {
		count, err = model.ProductVariationMeta(mods...).Count(ctx, r.mysqlConn)
		if err != nil {
			return
		}

		if withCount == 0 {
			return
		}
	}

	if pageSize > 0 && (withCount == -1 || withCount == 1) {
		if page > 1 {
			mods = append(mods, qm.Offset(pageSize*(page-1)))
		}
		mods = append(mods, qm.Limit(pageSize))
	}

	var columns []string
	if len(selectCol) > 0 {
		if selectCol == "," {
			columns = append(columns, model.ProductVariationMetumColumns.MetaID)
		} else {
			columns = strings.Split(selectCol, ",")
		}
	}
	if len(columns) > 0 {
		mods = append(mods, qm.Select(columns...))
	}

	list, err = model.ProductVariationMeta(mods...).All(ctx, r.mysqlConn)
	if err != nil {
		return
	}

	if withCount >= 2 {
		if limit > 0 && len(list) > limit {
			nextCount = 1
			list = list[:limit]
		}
		count = previousCount + nextCount*2
	}

	return
}

func (r *customCurrentProductRepository) InsertSearchLog(
	ctx context.Context,
	tx boil.ContextExecutor,
	data *model.ProductUserSearchLog,
) error {
	var db boil.ContextExecutor
	if tx != nil {
		db = tx
	} else {
		db = r.mysqlConn
	}

	return data.Insert(ctx, db, boil.Infer())
}
func (r *customCurrentProductRepository) UpdateProductVariationMeta(
	ctx context.Context,
	tx boil.ContextExecutor,
	meta []*model.ProductVariationMetum,
	delMetaIds []uint64,
) error {
	var db boil.ContextExecutor
	if tx != nil {
		db = tx
	} else {
		db = r.mysqlConn
	}

	if len(meta) > 0 {
		for _, metum := range meta {
			if metum.MetaID > 0 {
				_, err := metum.Update(ctx, db, boil.Whitelist(
					model.ProductVariationMetumColumns.MetaValue,
				))
				if err != nil {
					return err
				}
			} else {
				err := metum.Insert(ctx, db, boil.Infer())
				if err != nil {
					return err
				}
			}
		}
	}

	if len(delMetaIds) > 0 {
		var mods []qm.QueryMod
		mods = append(mods, model.ProductVariationMetumWhere.MetaID.IN(delMetaIds))
		_, err := model.ProductVariationMeta(mods...).DeleteAll(ctx, db)
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *customCurrentProductRepository) UpdateProductVariationMetum(
	ctx context.Context,
	tx boil.ContextExecutor,
	metum *model.ProductVariationMetum,
) error {
	if metum.ProductID > 0 && len(metum.MetaKey) > 0 {
		var db boil.ContextExecutor
		if tx != nil {
			db = tx
		} else {
			db = r.mysqlConn
		}

		var mods []qm.QueryMod
		mods = append(mods, model.ProductVariationMetumWhere.ProductID.EQ(metum.ProductID))
		mods = append(mods, model.ProductVariationMetumWhere.MetaKey.EQ(metum.MetaKey))
		list, err := model.ProductVariationMeta(mods...).All(ctx, db)
		if err != nil {
			if err == sql.ErrNoRows {
				return metum.Insert(ctx, db, boil.Infer())
			}

			return err
		}

		if len(list) == 0 {
			return metum.Insert(ctx, db, boil.Infer())
		}

		_, err = model.ProductVariationMeta(mods...).UpdateAll(ctx, db, model.M{
			model.ProductVariationMetumColumns.MetaValue: metum.MetaValue,
		})
		if err != nil {
			return err
		}
	}

	return nil
}
